/*
 * Copyright (c) 2003-2008 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package fwm;

import java.util.logging.Logger;

import javax.sound.midi.MidiSystem;
import javax.sound.midi.Soundbank;
import java.net.URL;


import com.jme.image.Texture;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.KeyInputListener;
import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.state.LightState;
import com.jme.scene.state.WireframeState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.geom.Debugger;
import com.jmex.effects.particles.ParticleMesh;
import com.jmex.game.state.TextGameState;


/**
 * Copied from TestGameState from Matthew D. Hicks
 */
public class FWMGameState extends TextGameState {
    private static final Logger logger = Logger.getLogger(FWMGameState.class
            .getName());
    
    protected InputHandler input;
    protected WireframeState wireState;
    protected LightState lightState;
    protected boolean pause;
    protected static boolean priorKeyEsc = false;
    protected static boolean priorPriorKeyEsc = false;
    

    public FWMGameState() {
        super("Esc 3 times to quit");
        init();
    }
    
    private void init() {
    	//block special keyboard keys
	    KeyBlock.startBlock();
	    
	    try {
	    Soundbank soundbank = MidiSystem.getSoundbank(FWMGameState.class.
	    		                   getClassLoader().getResourceAsStream("media/soundbank-deluxe.gm"));
	    } catch (Exception e) {System.err.println("soundbank " + e);}
    	
        rootNode = new Node("RootNode");

        // Create ZBuffer for depth
        ZBufferState zbs = DisplaySystem.getDisplaySystem().getRenderer()
                .createZBufferState();
        zbs.setEnabled(true);
        zbs.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
        rootNode.setRenderState(zbs);
        
        // Lighting
        /** Set up a basic, default light. */
        PointLight light = new PointLight();
        light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );
        light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 1.0f ) );
        light.setLocation( new Vector3f( 100, 100, 100 ) );
        light.setEnabled( true );

        /** Attach the light to a lightState and the lightState to rootNode. */
        lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
        lightState.setEnabled( true );
        lightState.attach( light );
        rootNode.setRenderState( lightState );

        // Initial InputHandler
        initKeyBindings();
        
        // Finish up
        rootNode.updateRenderState();
        rootNode.updateWorldBound();
        rootNode.updateGeometricState(0.0f, true);

        ExplosionFactory.warmup(rootNode);
        
    }
    
    public LightState getLightState() {
    	return lightState;
    }

    private void initKeyBindings() {
        
        KeyInput.get().addListener( new KeyInputListener() {
            public void onKey( char character, int keyCode, boolean pressed ) {
            	if (pressed) {
            		addExplosion(keyCode);

                	//exit after 3 Esc key presses in a row
                	if (keyCode == KeyInput.KEY_ESCAPE) {
                		if (priorKeyEsc) {
                			if (priorPriorKeyEsc) {
                				System.exit(0);
                			} else {
                    			priorKeyEsc = true;
                    			priorPriorKeyEsc = true;
                			}
                		} else {
                			priorKeyEsc = true;
                			priorPriorKeyEsc = false;
                		}            			
                	} else {
            			priorKeyEsc = false;
            			priorPriorKeyEsc = false;            		
                	}
            	}
            	
            	//System.out.println( "key: '" + (character != 0 ? ""+character : "\\0") + "' (code "+keyCode+") " + (pressed?"pressed":"released") );
            }
        } );        
    }

    public void update(float tpf) {
    	super.update(tpf);

        // Update the geometric state of the rootNode
        rootNode.updateGeometricState(tpf, true);
    }

    protected void cameraPerspective() {
        DisplaySystem display = DisplaySystem.getDisplaySystem();
        Camera cam = display.getRenderer().getCamera();
        cam.setFrustumPerspective(45.0f, (float) display.getWidth()
                / (float) display.getHeight(), 1, 1000);
        cam.setParallelProjection(false);
        cam.update();
    }

    protected void cameraParallel() {
        DisplaySystem display = DisplaySystem.getDisplaySystem();
        Camera cam = display.getRenderer().getCamera();
        cam.setParallelProjection(true);
        float aspect = (float) display.getWidth() / display.getHeight();
        cam.setFrustum(-100.0f, 1000.0f, -50.0f * aspect, 50.0f * aspect,
                -50.0f, 50.0f);
        cam.update();
    }

    public void render(float tpf) {
    	super.render(tpf);
    	
        // Render the rootNode
        DisplaySystem.getDisplaySystem().getRenderer().draw(rootNode);

    }

    public void cleanup() {
    	KeyBlock.unHook();
    }
    
    private void addExplosion(int keyCode) {
		ParticleMesh explosion;
		explosion = ExplosionFactory.getExplosion(keyCode);
		explosion.getLocalTranslation().set(
				((float) Math.random() - 0.5f) * 40f,
				((float) Math.random() - 0.5f) * 40f,
				((float) Math.random()) * -40f - 20f);				
		
		explosion.forceRespawn();
		ExplosionFactory.playSound(keyCode);

    }
}
